// Copyright (c) 2006 Zorm
// Released under the MIT License

#include "PCH.h"
#include "..\Common.h"

bool GLContext::Init() {
	
	m_windowDC = GetDC(m_windowHWND);
	PIXELFORMATDESCRIPTOR pfd;
	ZeroMemory(&pfd, sizeof(pfd));
	pfd.nSize = sizeof(pfd);
	pfd.nVersion = 1;
	pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
	pfd.cColorBits = 24;
	pfd.cDepthBits = 16;
	int format;
	if (!(format = ChoosePixelFormat(m_windowDC, &pfd))) {
		return false;
	}
	
	if (!SetPixelFormat(m_windowDC, format, &pfd)) {
		return false;
	}

	if (!(m_windowRC = wglCreateContext(m_windowDC))) {
		return false;
	}
	
	if (!wglMakeCurrent(m_windowDC, m_windowRC)) {
		return false;
	}
	
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glShadeModel(GL_FLAT);

	glEnable(GL_POLYGON_OFFSET_FILL);
	glPolygonOffset(0.0, 1.0);

	glDisable(GL_NORMALIZE);
	glDisable(GL_BLEND);
	glDisable(GL_DEPTH_TEST);
	
	m_fontBase = glGenLists(96);
	HFONT font, oldFont;
	font = CreateFont(-13, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_TT_PRECIS,
			CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE|DEFAULT_PITCH, TEXT("Tahoma"));
	oldFont = (HFONT)SelectObject(m_windowDC, font);
	wglUseFontBitmaps(m_windowDC, 32, 96, m_fontBase);
	SelectObject(m_windowDC, oldFont);
	DeleteObject(font);
	
	return true;
}

void GLContext::Swap() {
	SwapBuffers(m_windowDC);
}

void GLContext::Resize(int width, int height) {
	m_centerx = width/2;
	m_centery = height/2;
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, width, 0, height, 1.0, -1.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void GLContext::DrawString(int latitude, int longitude, double scale, char *text) {
	int offset = (int)ceil(10000 / (scale/.001));
	glRasterPos2i(latitude, longitude - offset);
	glPushAttrib(GL_LIST_BIT);
		glListBase(m_fontBase - 32);
		glCallLists((GLsizei)strlen(text), GL_UNSIGNED_BYTE, text);
	glPopAttrib();
}

void GLContext::Draw() {
	glPushMatrix();
		glTranslated(m_centerx, m_centery, 0.0);
		ATH::Instance()->GetRadarInfo()->Draw();
	glPopMatrix();
}

void GLContext::CaptureScreen(char *filename) {
	GLint viewport[4];
	FILE *outFile;
	if(fopen_s(&outFile, filename, "wb")) {
		return;
	}

	glGetIntegerv(GL_VIEWPORT, viewport);

	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if(!png_ptr) {
		fclose(outFile);
		return;
	}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if(!info_ptr) {
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		fclose(outFile);
		return;
	}

	png_init_io(png_ptr, outFile);
   
	// set the zlib compression level
	png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);

	// set other zlib parameters 
	png_set_compression_mem_level(png_ptr, 8);
	png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
	png_set_compression_window_bits(png_ptr, 15);
	png_set_compression_method(png_ptr, 8);
	png_set_compression_buffer_size(png_ptr, 8192);

	png_set_IHDR(png_ptr, info_ptr, viewport[2], viewport[3], 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
	png_write_info(png_ptr, info_ptr);

	if (setjmp(png_ptr->jmpbuf)) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fclose(outFile);
		return;
	}
   
	GLubyte *pixels = new GLubyte[viewport[2] * viewport[3] * 3];
	if (!pixels) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fclose(outFile);
		return;
	}

	glPixelStorei(GL_PACK_ALIGNMENT,1);
	glReadPixels(0, 0, viewport[2], viewport[3], GL_RGB, GL_UNSIGNED_BYTE, pixels);
	glPixelStorei(GL_PACK_ALIGNMENT,4);
	
	GLubyte** rowPtrs = new GLubyte*[viewport[3]];
	for(GLint i = 0; i < viewport[3]; i++) {
		rowPtrs[viewport[3] - i - 1] = &(pixels[i * viewport[2] * 3]);
	}

	png_write_image(png_ptr, rowPtrs);
	png_write_end(png_ptr, info_ptr);
	
	png_destroy_write_struct(&png_ptr, &info_ptr);
	delete [] pixels;
	delete [] rowPtrs;
	
	fclose(outFile);
}

void GLContext::LoadMatrix() {
    glGetDoublev(GL_MODELVIEW_MATRIX, m_modelView);
    glGetDoublev(GL_PROJECTION_MATRIX, m_projection);
    glGetIntegerv(GL_VIEWPORT, m_viewport);
};

bool GLContext::Unproject(double x, double y, double *lat, double *lon) {
	GLdouble objectX = 0, objectY = 0, objectZ = 0, realY = 0;
    realY = m_viewport[3] - y;
    if (gluUnProject(x, realY, 0, m_modelView, m_projection, m_viewport, &objectX, &objectY, &objectZ) == TRUE) {
		objectX /= 100000.0;
		objectX += ATH::Instance()->GetRadarInfo()->GetLongitude();
		objectY /= 100000.0;
		objectY += ATH::Instance()->GetRadarInfo()->GetLatitude();
		*lon = objectX;
		*lat = objectY;
		return true;
    }
    return false;
}